package com.igoal.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.igoal.dao.PrivacySettingDAO;
import com.igoal.dao.UserCheerDAO;
import com.igoal.dao.UserDAOExt;
import com.igoal.dao.UserGoalDAO;
import com.igoal.dao.UserGoalEntryDAO;
import com.igoal.dao.UserGoalEntryDoneDAO;
import com.igoal.dao.UserLikeDAO;
import com.igoal.dto.CommentEntryDTO;
import com.igoal.dto.FriendDTO;
import com.igoal.dto.GoalDTO;
import com.igoal.dto.UserDTO;
import com.igoal.dto.UserGoalEntryDTO;
import com.igoal.dto.UserGoalEntryDoneDTO;
import com.igoal.entity.ActionTypeEnum;
import com.igoal.entity.ComponentEnum;
import com.igoal.entity.DataStatus;
import com.igoal.entity.GoalStatusEnum;
import com.igoal.entity.PrivacyEnum;
import com.igoal.entity.PrivacySetting;
import com.igoal.entity.User;
import com.igoal.entity.UserCheer;
import com.igoal.entity.UserGoal;
import com.igoal.entity.UserGoalDone;
import com.igoal.entity.UserGoalEntry;
import com.igoal.entity.UserLike;
import com.igoal.entity.factory.EntityFactory;
import com.igoal.service.paging.PagingService;
import com.igoal.utils.StringUtils;

@Service("goalEntryManager")
public class GoalEntryManagerImpl extends BaseService<UserGoalEntryDTO, UserGoalEntry, Long>
		implements GoalEntryManager {

	@Qualifier("userDAOExt")
	private UserDAOExt userDAO;
	private UserGoalEntryDAO userGoalEntryDAO;
	private UserGoalEntryDoneDAO userGoalEntryDoneDAO;
	private UserLikeDAO userLikeDAO;
	private UserCheerDAO userCheerDAO;
	private UserGoalManager userGoalManager;
	private UserGoalDAO userGoalDAO;
	private PrivacySettingDAO privacySettingDAO;
	
	private ActionLoggerService actionLoggerService;
	private CommentService commentService;

	@Autowired
	public void setCommentService(CommentService commentService) {
		this.commentService = commentService;
	}

	@Autowired
	public void setUserGoalEntryDAO(UserGoalEntryDAO userGoalEntryDAO) {
		this.userGoalEntryDAO = userGoalEntryDAO;
	}

	@Autowired
	public void setUserGoalEntryDoneDAO(UserGoalEntryDoneDAO userGoalEntryDoneDAO) {
		this.userGoalEntryDoneDAO = userGoalEntryDoneDAO;
	}

	@Autowired
	public void setUserLikeDAO(UserLikeDAO userLikeDAO) {
		this.userLikeDAO = userLikeDAO;
	}
	
	@Autowired
	public void setUserCheerDAO(UserCheerDAO userCheerDAO) {
		this.userCheerDAO = userCheerDAO;
	}

	@Autowired
	public void setUserDAO(UserDAOExt userDAO) {
		this.userDAO = userDAO;
	}

	@Autowired
	public void setUserGoalDAO(UserGoalDAO userGoalDAO) {
		this.userGoalDAO = userGoalDAO;
	}

	@Autowired
	public void setUserGoalManager(UserGoalManager userGoalManager) {
		this.userGoalManager = userGoalManager;
	}

	@Autowired
	public void setActionLoggerService(ActionLoggerService actionLoggerService) {
		this.actionLoggerService = actionLoggerService;
	}
	
	@Autowired
	public void setPrivacySettingDAO(PrivacySettingDAO privacySettingDAO) {
		this.privacySettingDAO = privacySettingDAO;
	}

	public List<UserGoalEntry> getAll() {
		return userGoalEntryDAO.getAllDistinct();
	}

	public UserGoalEntry get(Long id) {
		UserGoalEntry goalEntry = userGoalEntryDAO.get(id);
		return goalEntry;
	}

	public boolean exists(Long id) {
		return userGoalEntryDAO.exists(id);
	}

	public UserGoalEntry save(UserGoalEntry object) {
		return userGoalEntryDAO.save(object);
	}

	public void remove(Long id) {
		userGoalEntryDAO.remove(id);
	}

	public UserGoalEntryDTO getGoalEntryByPrimaryKey(Long id) {
		UserGoalEntryDTO dto = new UserGoalEntryDTO();
		UserGoalEntry entity = get(id);
		if (entity != null) {
			dto.initFrom(entity);
			commentService.loadComments(dto, ComponentEnum.GOAL_ENTRY);
			return dto;
		}
		return null;
	}

	public int saveEntry(UserGoalEntryDTO dto) {
		String title = dto.getTitle();
		title = StringUtils.removeSpacesInsideString(title);
		title = StringUtils.removeHTMLTags(title);
		String body = dto.getBody();
		body = StringUtils.removeHTMLTags(body);
		
		UserGoalEntry entry = userGoalEntryDAO.get(dto.getId());
		entry.setTitle(title);
		entry.setBody(body);
		entry.setImgURL(dto.getImgURL());

		try {
			entry = userGoalEntryDAO.save(entry);
			return entry != null ? SaveResult.SUCCESS : SaveResult.FAIL;
		} catch (Exception e) {
			logger.error("", e);
			return SaveResult.FAIL;
		}
	}

	public int removeEntry(String username, Long id) {
		try{
			User user = (User) userDAO.loadUserByUsername(username);
			UserGoalEntry entry = userGoalEntryDAO.get(id);
			boolean allowDelete = false;
			if(user.equals(entry.getUser())){
				allowDelete = true; 
			}else if(isAdmin(user)){
				allowDelete = true;
			}
			if(allowDelete){
				remove(id);
				return SaveResult.SUCCESS;
			}
		}catch (Exception e) {
			logger.error(e);
		}		
		
		return SaveResult.FAIL;
	}

	public List<CommentEntryDTO> getCommentEntry(Long entryId) {
		return null;
	}

	public UserGoalEntryDTO getEntry(Long entryId, UserDTO currentUser) {
		UserGoalEntry entry = userGoalEntryDAO.get(entryId);
		UserGoalEntryDTO dto = new UserGoalEntryDTO();
		dto.initFrom(entry);

		// get like count
		int likeCount = userLikeDAO.countComponentLike(ComponentEnum.GOAL_ENTRY, entry.getId());
		dto.setLikeCount(likeCount);

		boolean isCurrentUserLikedThis = false;
		if (currentUser != null) {
			isCurrentUserLikedThis = userLikeDAO.isLikedThis(currentUser.getId(), ComponentEnum.GOAL_ENTRY, entry.getId());
		}
		dto.setYouLikeThis(isCurrentUserLikedThis);

		// get cheer count
		int cheerCount = userCheerDAO.countCheerThisComponent(ComponentEnum.GOAL_ENTRY, entry.getId());
		dto.setCheerCount(cheerCount);
		boolean isCurrentUserCheerThis = false;
		if (currentUser != null) {
			isCurrentUserCheerThis = userCheerDAO.isCheerThis(currentUser.getId(), ComponentEnum.GOAL_ENTRY, entry.getId());
		}
		dto.setYouCheerThis(isCurrentUserCheerThis);
		
		commentService.loadComments(dto, ComponentEnum.GOAL_ENTRY);
		return dto;
	}

	public UserGoalEntryDoneDTO getEntryDone(Long entryId, UserDTO currentUser) {
		UserGoalDone entry = userGoalEntryDoneDAO.get(entryId);
		UserGoalEntryDoneDTO dto = new UserGoalEntryDoneDTO();
		dto.initFrom(entry);

		// get like count
		int likeCount = userLikeDAO
				.countComponentLike(ComponentEnum.DONE_ENTRY, entry.getId());
		dto.setLikeCount(likeCount);

		boolean isCurrentUserLikedThis = false;
		if (currentUser != null) {
			isCurrentUserLikedThis = userLikeDAO.isLikedThis(currentUser.getId(),
					ComponentEnum.DONE_ENTRY, entry.getId());
		}
		dto.setYouLikeThis(isCurrentUserLikedThis);
		
		// get cheer count
		int cheerCount = userCheerDAO.countCheerThisComponent(ComponentEnum.GOAL_ENTRY,
				entry.getId());
		dto.setCheerCount(cheerCount);
		boolean isCurrentUserCheerThis = false;
		if (currentUser != null) {
			isCurrentUserCheerThis = userCheerDAO.isCheerThis(currentUser.getId(),
					ComponentEnum.DONE_ENTRY, entry.getId());
		}
		dto.setYouCheerThis(isCurrentUserCheerThis);

		commentService.loadComments(dto, ComponentEnum.DONE_ENTRY);
		return dto;
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List getRecentEntries(UserDTO user, UserDTO currentUser) {
		if (user == null) {
			return null;
		}

		List recentEntries = new ArrayList();

		List<UserGoalEntry> entries = userGoalEntryDAO.listEntriesByUser(user.getId(),
				PagingService.MAX_ENTRIES, PagingService.SORT_ENTRY_BY_PROPERTY);
		if (entries != null && entries.size() > 0) {
			for (UserGoalEntry entry : entries) {
				UserGoalEntryDTO recentEntry = new UserGoalEntryDTO();

				recentEntry.initFrom(entry);

				int likeCount = userLikeDAO.countComponentLike(ComponentEnum.GOAL_ENTRY,
						entry.getId());
				recentEntry.setLikeCount(likeCount);

				boolean isCurrentUserLikedThis = false;
				if (currentUser != null) {
					isCurrentUserLikedThis = userLikeDAO.isLikedThis(currentUser.getId(),
							ComponentEnum.GOAL_ENTRY, entry.getId());
				}
				recentEntry.setYouLikeThis(isCurrentUserLikedThis);
				
				commentService.loadComments(recentEntry, ComponentEnum.GOAL_ENTRY);
				
				recentEntries.add(recentEntry);
				debug("The entry[" + entry.getTitle() + "] has" + entry.getComments().size()
						+ " comment(s).");
			}
		}

		List<UserGoalDone> doneEntries = userGoalEntryDoneDAO.listDoneEntriesByUser(user.getId(),
				PagingService.MAX_ENTRIES, PagingService.SORT_ENTRY_BY_PROPERTY);
		if (doneEntries != null && doneEntries.size() > 0) {
			for (UserGoalDone entry : doneEntries) {
				UserGoalEntryDoneDTO recentEntry = new UserGoalEntryDoneDTO();

				recentEntry.initFrom(entry);

				int likeCount = userLikeDAO.countComponentLike(ComponentEnum.DONE_ENTRY,
						entry.getId());
				recentEntry.setLikeCount(likeCount);

				boolean isCurrentUserLikedThis = userLikeDAO.isLikedThis(user.getId(),
						ComponentEnum.DONE_ENTRY, entry.getId());
				recentEntry.setYouLikeThis(isCurrentUserLikedThis);

				commentService.loadComments(recentEntry, ComponentEnum.DONE_ENTRY);
				
				recentEntries.add(recentEntry);
				debug("The done entry[" + entry.getTitle() + "] has" + entry.getComments().size()
						+ " comment(s).");
			}
		}

		return recentEntries;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public List getRecentEntries(GoalDTO goalDTO, UserDTO userDTO) {
		List recentEntries = new ArrayList();
		if (goalDTO == null)
			return recentEntries;

		List<UserGoalEntry> entries = userGoalEntryDAO.listEntriesByGoal(
				goalDTO.getId(), PagingService.MAX_ENTRIES, PagingService.SORT_ENTRY_BY_PROPERTY);
		if (entries != null && entries.size() > 0) {
			for (UserGoalEntry entry : entries) {
				UserGoalEntryDTO recentEntry = new UserGoalEntryDTO();
				recentEntry.initFrom(entry);

				int likeCount = userLikeDAO.countComponentLike(
						ComponentEnum.GOAL_ENTRY, entry.getId());
				recentEntry.setLikeCount(likeCount);

				// Has loggined user?
				if (isLoginUser()) {
					String username = getUserInSession();
					User user = (User) userDAO.loadUserByUsername(username);
					Assert.notNull(user);

					boolean isCurrentUserLikedThis = userLikeDAO.isLikedThis(
							user.getId(), ComponentEnum.GOAL_ENTRY, entry.getId());
					recentEntry.setYouLikeThis(isCurrentUserLikedThis);
				}
				
				commentService.loadComments(recentEntry, ComponentEnum.GOAL_ENTRY);

				recentEntries.add(recentEntry);
			}
		}

		List<UserGoalDone> doneEntries = userGoalEntryDoneDAO
				.listDoneEntriesByGoal(goalDTO.getId(),
						PagingService.MAX_ENTRIES, PagingService.SORT_ENTRY_BY_PROPERTY);
		if (doneEntries != null && doneEntries.size() > 0) {
			for (UserGoalDone entry : doneEntries) {
				UserGoalEntryDoneDTO recentEntry = new UserGoalEntryDoneDTO();
				recentEntry.initFrom(entry);

				int likeCount = userLikeDAO.countComponentLike(
						ComponentEnum.DONE_ENTRY, entry.getId());
				recentEntry.setLikeCount(likeCount);

				if (isLoginUser()) {
					String username = getUserInSession();
					User user = (User) userDAO.loadUserByUsername(username);
					Assert.notNull(user);

					boolean isCurrentUserLikedThis = userLikeDAO.isLikedThis(
							user.getId(), ComponentEnum.DONE_ENTRY, entry.getId());
					recentEntry.setYouLikeThis(isCurrentUserLikedThis);
				}
				
				commentService.loadComments(recentEntry, ComponentEnum.DONE_ENTRY);

				recentEntries.add(recentEntry);
				debug("The done entry[" + entry.getTitle() + "] has"
						+ entry.getComments().size() + " comment(s).");
			}
		}
		return recentEntries;
	}
	
	public UserGoalEntryDoneDTO getGoalDoneEntry(Long goalId, Long userId) {
		List<UserGoalDone> entries = userGoalEntryDoneDAO.findByFK(userId,
				goalId);
		if (entries != null && !entries.isEmpty()) {
			// each usergoal has only one usergoaldone
			UserGoalEntryDoneDTO dto = new UserGoalEntryDoneDTO();
			UserGoalDone entity = entries.get(0);
			dto.initFrom(entity);
			
			commentService.loadComments(dto, ComponentEnum.DONE_ENTRY);
			
			return dto;
		}
		return null;
	}
	
	public List<UserGoalEntryDoneDTO> getRecentDoneEntries(Long goalId) {
		List<UserGoalDone> entries = userGoalEntryDoneDAO.listDoneEntriesByGoal(goalId, 5, "updateDate");
		if (entries != null && entries.size() > 0) {
			List<UserGoalEntryDoneDTO> recentEntries = new ArrayList<UserGoalEntryDoneDTO>();
			for (UserGoalDone entry : entries) {
				UserGoalEntryDoneDTO recentEntry = new UserGoalEntryDoneDTO();
				recentEntry.initFrom(entry);

				int likeCount = userLikeDAO.countComponentLike(
						ComponentEnum.DONE_ENTRY, entry.getId());
				recentEntry.setLikeCount(likeCount);

				// Has loggined user?
				if (isLoginUser()) {
					String username = getUserInSession();
					User user = (User) userDAO.loadUserByUsername(username);
					Assert.notNull(user);

					boolean isCurrentUserLikedThis = userLikeDAO.isLikedThis(
							user.getId(), ComponentEnum.DONE_ENTRY, entry.getId());
					recentEntry.setYouLikeThis(isCurrentUserLikedThis);
				}
				
				commentService.loadComments(recentEntry, ComponentEnum.DONE_ENTRY);

				recentEntries.add(recentEntry);
			}
			return recentEntries;
		}

		return null;
	}
	
	public int createNewGoalEntry(UserGoalEntryDTO dto, UserDTO user) {
		UserGoal userGoal = userGoalDAO.findByPK(user.getId(), dto.getGoalId());
		// add goal to user first
		if (userGoal == null) {
			GoalDTO goalDTO = new GoalDTO();
			goalDTO.setTitle(dto.getGoalTitle());
			userGoalManager.createNewGoal(goalDTO, user);
		} else {
			// restore it
			if (DataStatus.DELETED.equals(userGoal.getStatus())) {
				userGoal.setStatus(DataStatus.USING);
				userGoalDAO.save(userGoal);
			}
		}

		UserGoalEntry entry = EntityFactory.createUserGoalEntry(userGoal);

		// set privacy
		PrivacySetting privacy = privacySettingDAO.getPrivacy(PrivacyEnum.PUBLIC);
		entry.setPrivacy(privacy);
		
		String title = dto.getTitle();
		title = com.igoal.utils.StringUtils.removeSpacesInsideString(title);
		title = com.igoal.utils.StringUtils.removeAllHTMLTags(title);

		String body = dto.getBody();
		body = com.igoal.utils.StringUtils.removeHTMLTags(body);

		dto.copyAttributesTo(entry);
		entry.setTitle(title);
		entry.setBody(body);
		entry.setCheerCount(0);
		entry.setCommentCount(0);

		try {
			entry = userGoalEntryDAO.save(entry);
			
			int result = entry != null ? SaveResult.SUCCESS : SaveResult.FAIL;
			
			if(SaveResult.SUCCESS == result){
				User userEntity = userGoal.getUser();
				updateEntity(userEntity);
				userDAO.save(userEntity);
				
				actionLoggerService.log(entry.getUser(), entry.getUser(), ActionTypeEnum.NEW, ComponentEnum.GOAL_ENTRY, entry.getId());
			}
			
			return result;
		} catch (Exception e) {
			logger.error(e);
			return SaveResult.FAIL;
		}
	}
	
	public int updateGoalEntry(UserGoalEntryDTO dto) {
		if (dto == null)
			return SaveResult.FAIL;

		try {
			UserGoalEntry entry = userGoalEntryDAO.get(dto.getId());
			dto.copyAttributesTo(entry);
			userGoalEntryDAO.save(entry);
			
			User owner = entry.getUser();
			updateEntity(owner);
			userDAO.save(owner);
			
			return SaveResult.SUCCESS;
		} catch (ObjectRetrievalFailureException e) {
			logger.error(e);
		} catch (Exception e) {
			logger.error(e);
		}
		return SaveResult.FAIL;
	}
	
	public int deleteGoalEntry(String username, Long entryId) {
		if (username == null || entryId < 0)
			return SaveResult.FAIL;

		try {
			// UserDetails ud = userDAO.loadUserByUsername(username);
			// TODO: check permission

			UserGoalEntry entry = userGoalEntryDAO.get(entryId);

			if (!entry.getUserGoal().getUser().getUsername().equals(username)) {
				logger
						.info("###User["
								+ username
								+ "] requests delete an entry but is not belong to him.");
				return SaveResult.FAIL;
			}

			entry.setUpdateDate(new Date());
			entry.setStatus(DataStatus.DELETED);
			userGoalEntryDAO.save(entry);
			
			User owner = entry.getUser();
			updateEntity(owner);
			userDAO.save(owner);
			
			return SaveResult.SUCCESS;
		} catch (ObjectRetrievalFailureException e) {
			logger.error(e);
		} catch (Exception e) {
			logger.error(e);
		}
		return SaveResult.FAIL;
	}
	
	public int createNewGoalDone(UserGoalEntryDoneDTO dto, UserDTO user) {
		UserGoal userGoal = userGoalDAO.findByPK(user.getId(), dto.getGoalId());
		// add goal to user first
		if (userGoal == null) {
			GoalDTO goalDTO = new GoalDTO();
			goalDTO.setTitle(dto.getGoalTitle());
			userGoalManager.createNewGoal(goalDTO, user);
		} else {
			// restore it
			if (DataStatus.DELETED.equals(userGoal.getStatus())) {
				userGoal.setStatus(DataStatus.USING);
				userGoalDAO.save(userGoal);
			}
		}

		UserGoalDone entry = EntityFactory.createUserGoalDone(userGoal);
		
		// set privacy
		PrivacySetting privacy = privacySettingDAO.getPrivacy(PrivacyEnum.PUBLIC);
		entry.setPrivacy(privacy);

		String title = dto.getTitle();
		title = com.igoal.utils.StringUtils.removeSpacesInsideString(title);
		title = com.igoal.utils.StringUtils.removeAllHTMLTags(title);

		String solution = dto.getSolution();
		solution = com.igoal.utils.StringUtils.removeHTMLTags(solution);

		String tip = dto.getTip();
		tip = com.igoal.utils.StringUtils.removeHTMLTags(tip);

		String exp = dto.getExperience();
		exp = com.igoal.utils.StringUtils.removeHTMLTags(exp);

		dto.copyAttributesTo(entry);
		entry.setTitle(title);
		entry.setSolution(solution);
		entry.setTip(tip);
		entry.setExperience(exp);
		entry.setCheerCount(0);
		entry.setCommentCount(0);

		try {
			entry = userGoalEntryDoneDAO.save(entry);

			userGoal.setGoalStatus(GoalStatusEnum.FINISHED);
			userGoal.setUpdateDate(new Date());
			userGoalDAO.save(userGoal);

			int result = entry != null ? SaveResult.SUCCESS : SaveResult.FAIL;
			
			if(SaveResult.SUCCESS == result){
				User userEntity = userGoal.getUser();
				updateEntity(userEntity);
				userDAO.save(userEntity);
				
				actionLoggerService.log(entry.getUser(), entry.getUser(), ActionTypeEnum.NEW, ComponentEnum.DONE_ENTRY, entry.getId());
			}
			
			return result;
		} catch (Exception e) {
			logger.error(e);
			return SaveResult.FAIL;
		}
	}
	
	public int updateGoalDone(UserGoalEntryDoneDTO dto) {
		if (dto == null)
			return SaveResult.FAIL;

		try {
			UserGoalDone entry = userGoalEntryDoneDAO.get(dto.getId());
			dto.copyAttributesTo(entry);
			userGoalEntryDoneDAO.save(entry);
			
			User owner = entry.getUser();
			updateEntity(owner);
			userDAO.save(owner);
			
			return SaveResult.SUCCESS;
		} catch (ObjectRetrievalFailureException e) {
			logger.error(e);
		} catch (Exception e) {
			logger.error(e);
		}
		return SaveResult.FAIL;
	}
	
	public int deleteGoalDone(UserGoalEntryDoneDTO dto) {
		if (dto == null)
			return SaveResult.FAIL;

		try {
			UserGoalDone comment = userGoalEntryDoneDAO.get(dto.getId());
			comment.setUpdateDate(new Date());
			comment.setStatus(DataStatus.DELETED);
			userGoalEntryDoneDAO.save(comment);
			
			User owner = comment.getUser();
			updateEntity(owner);
			userDAO.save(owner);
			
			return SaveResult.SUCCESS;
		} catch (ObjectRetrievalFailureException e) {
			logger.error(e);
			return SaveResult.FAIL;
		} catch (Exception e) {
			logger.error(e);
			return SaveResult.FAIL;
		}
	}
	
	public int countGoalEntry(Long goalId) {
		List<UserGoalEntry> entries = userGoalEntryDAO.listEntriesByGoal(
				goalId, -1, null);
		return entries.size();
	}

	public int countGoalEntry(Long goalId, Long userId) {
		List<UserGoalEntry> entries = userGoalEntryDAO.findByFK(userId, goalId);
		return entries.size();
	}
	
	public List<UserGoalDone> getAllSolutions(Long goalId) {
		return userGoalEntryDoneDAO.listDoneEntriesByGoal(goalId, -1, null);
	}
	
	public List<UserGoalEntryDTO> getEntriesByPaging(
			Map<String, Object> criteria, String orderProperty,
			Object lastOrderPropertyValue, boolean before) {
		List<UserGoalEntry> entries = userGoalEntryDAO
				.pagingDependOnOrderProperty(criteria, orderProperty,
						lastOrderPropertyValue, before,
						PagingService.MAX_ENTRIES);
		if (entries != null) {
			List<UserGoalEntryDTO> result = new ArrayList<UserGoalEntryDTO>();
			for (UserGoalEntry entry : entries) {
				UserGoalEntryDTO entryDTO = new UserGoalEntryDTO();
				// dto.initCommentsFromEntity(entry);
				entryDTO.initFrom(entry);

				int likeCount = userLikeDAO.countComponentLike(
						ComponentEnum.GOAL_ENTRY, entry.getId());
				entryDTO.setLikeCount(likeCount);

				if (isLoginUser()) {
					String username = getUserInSession();
					User user = (User) userDAO.loadUserByUsername(username);
					Assert.notNull(user);

					boolean isCurrentUserLikedThis = userLikeDAO.isLikedThis(
							user.getId(), ComponentEnum.GOAL_ENTRY, entry.getId());
					entryDTO.setYouLikeThis(isCurrentUserLikedThis);
				}
				
				commentService.loadComments(entryDTO, ComponentEnum.GOAL_ENTRY);

				result.add(entryDTO);
				debug("The entry[" + entry.getTitle() + "] has"
						+ entry.getComments().size() + " comment(s).");
			}

			return result;
		}

		return null;
	}
	
	public List<UserGoalEntryDoneDTO> getDoneEntriesByPaging(
			Map<String, Object> criteria, String orderProperty,
			Object lastOrderPropertyValue, boolean before) {
		// if(!criteria.containsKey("goalId"))
		// return null;

		List<UserGoalDone> entries = userGoalEntryDoneDAO
				.pagingDependOnOrderProperty(criteria, orderProperty,
						lastOrderPropertyValue, before,
						PagingService.MAX_ENTRIES);
		if (entries != null && entries.size() > 0) {
			List<UserGoalEntryDoneDTO> result = new ArrayList<UserGoalEntryDoneDTO>();
			for (UserGoalDone entry : entries) {
				UserGoalEntryDoneDTO entryDTO = new UserGoalEntryDoneDTO();
				entryDTO.initFrom(entry);

				int likeCount = userLikeDAO.countComponentLike(
						ComponentEnum.DONE_ENTRY, entry.getId());
				entryDTO.setLikeCount(likeCount);

				// Has loggined user?
				if (isLoginUser()) {
					String username = getUserInSession();
					User user = (User) userDAO.loadUserByUsername(username);
					Assert.notNull(user);

					boolean isCurrentUserLikedThis = userLikeDAO.isLikedThis(
							user.getId(), ComponentEnum.DONE_ENTRY, entry.getId());
					entryDTO.setYouLikeThis(isCurrentUserLikedThis);
				}
				
				commentService.loadComments(entryDTO, ComponentEnum.DONE_ENTRY);

				result.add(entryDTO);
			}
			return result;
		}

		return null;
	}
	
	public int countEntryLike(Long entryId, boolean isEntryDone) {
		ComponentEnum com = isEntryDone ? ComponentEnum.DONE_ENTRY : ComponentEnum.GOAL_ENTRY;
		return userLikeDAO.countComponentLike(com, entryId);
	}
	
	public List<FriendDTO> getRandomEntryLikeList(Long userId, Long entryId, boolean isEntryDone) {
		ComponentEnum com = isEntryDone ? ComponentEnum.DONE_ENTRY : ComponentEnum.GOAL_ENTRY;
		List<UserLike> likeList = userLikeDAO.getRandomeLikeList(userId, com, entryId);
		List<FriendDTO> result = new ArrayList<FriendDTO>();
		if (likeList != null && likeList.size() > 0) {
			for (UserLike ul : likeList) {
				User u = ul.getUser();
				FriendDTO dto = new FriendDTO();
				dto.initFrom(u);
				result.add(dto);
			}
		}
		return result;
	}

	public List<FriendDTO> getEntryLikePage(Long entryId, boolean isEntryDone, int pageNumber) {
		ComponentEnum com = isEntryDone ? ComponentEnum.DONE_ENTRY : ComponentEnum.GOAL_ENTRY;
		List<UserLike> likeList = userLikeDAO.getUserLikedThisComponent(com, entryId, pageNumber);
		List<FriendDTO> result = new ArrayList<FriendDTO>();
		if (likeList != null && likeList.size() > 0) {
			for (UserLike ul : likeList) {
				User u = ul.getUser();
				FriendDTO dto = new FriendDTO();
				dto.initFrom(u);
				result.add(dto);
			}
		}
		return result;
	}

	public List<FriendDTO> getEntryCheerPage(Long entryId, boolean isEntryDone, int pageNumber) {
		ComponentEnum com = isEntryDone ? ComponentEnum.DONE_ENTRY : ComponentEnum.GOAL_ENTRY;
		List<UserCheer> cheerList = userCheerDAO.getUserCheeredThisComponent(com, entryId,
				pageNumber);
		List<FriendDTO> result = new ArrayList<FriendDTO>();
		if (cheerList != null && cheerList.size() > 0) {
			for (UserCheer ul : cheerList) {
				User u = ul.getUser();
				FriendDTO dto = new FriendDTO();
				dto.initFrom(u);
				result.add(dto);
			}
		}
		return result;
	}

}
